package rtool

import (
	"archive/zip"
	"io"
	"os"
	"path"
	"strings"

	"golang.org/x/text/encoding/simplifiedchinese"
)

type ZipFileItem struct {
	Content  []byte `json:"'content'"`
	Filepath string `json:"filepath"`
}

// ZipSave 保存为zip文件
// content 文件内容
// filepath 文件在zip里面的路径
// zipFilepath zip文件保存在本地磁盘的路径
func ZipSave(content []byte, filepath string, zipFilepath string) error {
	zFile, err := os.Create(zipFilepath)
	if err != nil {
		return err
	}
	defer zFile.Close()
	writer := zip.NewWriter(zFile)
	defer writer.Close()
	create, err := writer.Create(filepath)
	if err != nil {
		return err
	}
	_, err = create.Write(content)
	return err
}

// ZipSaveAs 保存为zip文件
func ZipSaveAs(srcFilepath string, zipFilepath string, isDeleteSrc bool) error {
	srcFile, err := os.Open(srcFilepath)
	if err != nil {
		return err
	}
	zFile, err := os.Create(zipFilepath)
	if err != nil {
		return err
	}
	defer zFile.Close()
	writer := zip.NewWriter(zFile)
	defer writer.Close()
	create, err := writer.Create(path.Base(srcFilepath))
	if err != nil {
		return err
	}
	_, err = io.Copy(create, srcFile)
	srcFile.Close()
	if isDeleteSrc {
		_ = os.Remove(srcFilepath)
	}
	return err
}

// ZipSaveList 保存为zip文件
// list 文件列表
// zipFilepath zip文件保存在本地磁盘的路径
func ZipSaveList(list []ZipFileItem, zipFilepath string) error {
	zFile, err := os.Create(zipFilepath)
	if err != nil {
		return err
	}
	defer zFile.Close()
	writer := zip.NewWriter(zFile)
	defer writer.Close()
	for _, d := range list {
		create, err := writer.Create(d.Filepath)
		if err != nil {
			return err
		}
		_, err = create.Write(d.Content)
		if err != nil {
			return err
		}
	}
	return err
}

// ZipSaveByDir 将指定文件夹压缩成zip文件
// dir 文件夹路径
// zipFilepath zip文件保存在本地磁盘的路径
// skipReadErr 是否跳过读源文件错误
func ZipSaveByDir(dir string, zipFilepath string, skipReadErr bool) error {
	zFile, err := os.Create(zipFilepath)
	if err != nil {
		return err
	}
	defer zFile.Close()
	writer := zip.NewWriter(zFile)
	defer writer.Close()
	allFileList, err := RangeDirFile(dir)
	if err != nil {
		return err
	}
	dir = strings.ReplaceAll(dir, `\`, "/")
	var length = 0
	if len(path.Dir(path.Join(dir))) > 1 {
		length = len(path.Dir(path.Join(dir)))
	}
	for _, d := range allFileList {
		all, err := os.ReadFile(d)
		if err != nil {
			if skipReadErr {
				continue
			}
			return err
		}
		create, err := writer.Create(d[length:])
		if err != nil {
			return err
		}
		_, err = create.Write(all)
		if err != nil {
			return err
		}
	}
	return err
}

// Unzip 解压zip文件
func Unzip(zipFilepath string, toDir string) error {
	reader, err := zip.OpenReader(zipFilepath)
	if err != nil {
		return err
	}
	defer reader.Close()
	for _, d := range reader.File {
		name := d.Name
		if d.NonUTF8 {
			s, err := simplifiedchinese.GBK.NewDecoder().String(d.Name)
			if err == nil {
				name = s
			}
		}
		if len(toDir) > 0 {
			name = path.Join(toDir, name)
		}
		if d.FileInfo().IsDir() {
			_ = os.MkdirAll(name, d.Mode())
		} else {
			file, err := os.OpenFile(name, os.O_CREATE|os.O_WRONLY, d.Mode())
			if err == nil {
				raw, err := d.Open()
				if err == nil {
					io.Copy(file, raw)
				}
				file.Close()
			}
		}
	}
	return nil
}
